package cn.caplike.demo.repository.java8;

import java.util.Arrays;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * Description:
 *
 * @author LiKe
 * @version 1.0.0
 * @date 2021-09-11 19:44
 */
public class RuleServiceX<T> {
    private Predicate and;
    private Predicate or;

    public static RuleServiceX create() {
        return new RuleServiceX();
    }

    public static Predicate ruleAnd(Predicate... operations) {
        return Arrays.stream(operations).reduce(Predicate::and).orElse(t -> true);
    }

    public static Predicate ruleOr(Predicate... operations) {
        return Arrays.stream(operations).reduce(Predicate::or).orElse(t -> true);
    }

    public static Predicate operation(Function extractor, Predicate condition) {
        return t -> condition.test(extractor.apply(t));
    }

    public RuleServiceX and(Predicate and) {
        this.and = and;
        return this;
    }

    public RuleServiceX or(Predicate or) {
        this.or = or;
        return this;
    }

    public boolean execute(T dto) {
        boolean result = false;
        if (and != null) {
            result = and.test(dto);
        }
        if (!result) {
            if (or != null) {
                result = or.test(dto);
            }
        }
        return result;
    }

    // -----------------------------------------------------------------------------------------------------------------

//    public static void main(String[] args) {
//        RuleDto dto = new RuleDto();
//        dto.setAge(19);
//        dto.setName("张三");
//        dto.setAddress("北京");
//        dto.setSubject("数学");
//
//        Predicate ruleAnd = RuleServiceX.ruleAnd(
//                operation(RuleDto::getAge, p -> p >= 20),
//                operation(RuleDto::getAddress, p -> p.startsWith("北京")),
//                operation(RuleDto::getName, p -> p.contains("张三")));
//
//        Predicate ruleOr = RuleServiceX.ruleOr(
//                operation(RuleDto::getAge, p -> p >= 10),
//                operation(RuleDto::getAddress, p -> p.startsWith("a")),
//                operation(RuleDto::getName, p -> p.contains("a")));
//
//        RuleServiceX serviceX = new RuleServiceX<RuleDto>();
//        boolean ruleResult = serviceX.create().and(ruleAnd).or(ruleOr).execute(dto);
//        System.out.println("this student rule execute result :" + ruleResult);
//    }
}